package cn.cuilan.common.core;

/**
 * 连接器配置类
 *
 * @author zhang.yan
 */
public abstract class ConnectorConfiguration {

    /**
     * 默认读写超时等待时间.
     * {@link #idleTimeout}  (ping interval) = 30 sec.
     */
    private static final int DEFAULT_IDLE_TIMEOUT_SECONDS = 30;

    /**
     * 默认最大长度.
     * {@link #maxFrameLength} (max message length) = 81920.
     */
    private static final int DEFAULT_MAX_FRAME_LENGTH = 81920;

    /**
     * 默认长度所占字节数.
     * {@link #frameLengthFieldLength} (length of TCP Frame length) = 4
     */
    private static final int DEFAULT_FRAME_LENGTH_FIELD_LENGTH = 4;

    /**
     * 默认长度字节调整/补偿量.
     * {@link #frameLengthFieldAdjust} (compensation value to add to the value of the length field) = 0
     */
    private static final int DEFAULT_FRAME_LENGTH_FIELD_ADJUST = 0;

    /**
     * 默认长度字节偏移量.
     * {@link #frameLengthFieldOffset} (the offset of the length field) = 0
     */
    private static final int DEFAULT_FRAME_LENGTH_FIELD_OFFSET = 0;

    private int maxFrameLength;
    private final int frameLengthFieldLength;
    private final int frameLengthFieldOffset;
    private final int frameLengthFieldAdjust;
    private final int workerThreadsCount;
    private int idleTimeout;
    private boolean replyOnError;
    private boolean addLoggingHandler;
    private boolean logSensitiveData;
    private boolean idleEventHandler;
    private int[] sensitiveDataFields;
    private boolean logFieldDescription;


    protected ConnectorConfiguration(final Builder builder) {
        maxFrameLength = builder.maxFrameLength;
        frameLengthFieldLength = builder.frameLengthFieldLength;
        frameLengthFieldAdjust = builder.frameLengthFieldAdjust;
        frameLengthFieldOffset = builder.frameLengthFieldOffset;
        workerThreadsCount = builder.workerThreadsCount;
        idleTimeout = builder.idleTimeout;
        replyOnError = builder.replyOnError;
        addLoggingHandler = builder.addLoggingHandler;
        logSensitiveData = builder.logSensitiveData;
        idleEventHandler = builder.idleEventHandler;
        sensitiveDataFields = builder.sensitiveDataFields;
        logFieldDescription = builder.logFieldDescription;
    }

    public int getMaxFrameLength() {
        return maxFrameLength;
    }

    @Deprecated
    public void setMaxFrameLength(int maxFrameLength) {
        this.maxFrameLength = maxFrameLength;
    }

    public int getIdleTimeout() {
        return idleTimeout;
    }

    @Deprecated
    public void setIdleTimeout(int idleTimeoutSeconds) {
        this.idleTimeout = idleTimeoutSeconds;
    }

    @Deprecated
    public void setAddLoggingHandler(boolean addLoggingHandler) {
        this.addLoggingHandler = addLoggingHandler;
    }

    public boolean addLoggingHandler() {
        return addLoggingHandler;
    }

    /**
     * 返回心跳状态
     *
     * @return 如果启用心跳则返回真
     */
    public boolean idleEventHandler() {
        return idleEventHandler;
    }

    public boolean replyOnError() {
        return replyOnError;
    }

    @Deprecated
    public void setReplyOnError(boolean replyOnError) {
        this.replyOnError = replyOnError;
    }

    public boolean logSensitiveData() {
        return logSensitiveData;
    }

    @Deprecated
    public void setLogSensitiveData(boolean logSensitiveData) {
        this.logSensitiveData = logSensitiveData;
    }

    public boolean logFieldDescription() {
        return logFieldDescription;
    }

    @Deprecated
    public void setLogFieldDescription(boolean logFieldDescription) {
        this.logFieldDescription = logFieldDescription;
    }

    public int[] getSensitiveDataFields() {
        return sensitiveDataFields;
    }

    @Deprecated
    public void setSensitiveDataFields(int[] sensitiveDataFields) {
        this.sensitiveDataFields = sensitiveDataFields;
    }

    public int getWorkerThreadsCount() {
        return workerThreadsCount;
    }

    public int getFrameLengthFieldLength() {
        return frameLengthFieldLength;
    }

    public int getFrameLengthFieldOffset() {
        return frameLengthFieldOffset;
    }

    public int getFrameLengthFieldAdjust() {
        return frameLengthFieldAdjust;
    }

    @SuppressWarnings({"unchecked", "WeakerAccess", "UnusedReturnValue"})
    protected abstract static class Builder<B extends Builder<B>> {

        private boolean addLoggingHandler = false;
        private boolean idleEventHandler = false;
        private boolean logFieldDescription = true;
        private boolean logSensitiveData = true;
        private boolean replyOnError = false;
        private int idleTimeout = DEFAULT_IDLE_TIMEOUT_SECONDS;
        private int maxFrameLength = DEFAULT_MAX_FRAME_LENGTH;
        private int workerThreadsCount = 0; // use netty default
        private int[] sensitiveDataFields;
        private int frameLengthFieldLength = DEFAULT_FRAME_LENGTH_FIELD_LENGTH;
        private int frameLengthFieldOffset = DEFAULT_FRAME_LENGTH_FIELD_OFFSET;
        private int frameLengthFieldAdjust = DEFAULT_FRAME_LENGTH_FIELD_ADJUST;

        public B maxFrameLength(int length) {
            this.maxFrameLength = length;
            return (B) this;
        }

        @Deprecated
        public B withMaxFrameLength(int length) {
            return maxFrameLength(length);
        }

        public B idleTimeout(int timeout) {
            this.idleTimeout = timeout;
            return (B) this;
        }

        @Deprecated
        public B withIdleTimeout(int timeout) {
            return idleTimeout(timeout);
        }

        public B replyOnError(boolean doReply) {
            this.replyOnError = doReply;
            return (B) this;
        }

        @Deprecated
        public B withReplyOnError(boolean doReply) {
            return replyOnError(doReply);
        }

        public B addLoggingHandler() {
            this.addLoggingHandler = true;
            return (B) this;
        }

        public B addLoggingHandler(boolean value) {
            this.addLoggingHandler = value;
            return (B) this;
        }

        public B withAddLoggingHandler(boolean addLoggingHandler) {
            this.addLoggingHandler = addLoggingHandler;
            return (B) this;
        }

        public B logSensitiveData(boolean logSensitiveData) {
            this.logSensitiveData = logSensitiveData;
            return (B) this;
        }

        public B withLogSensitiveData(boolean logSensitiveData) {
            this.logSensitiveData = logSensitiveData;
            return (B) this;
        }

        public B describeFieldsInLog() {
            this.logFieldDescription = true;
            return (B) this;
        }

        @Deprecated
        public B withLogFieldDescription(boolean logFieldDescription) {
            this.logFieldDescription = logFieldDescription;
            return (B) this;
        }

        public B sensitiveDataFields(int... sensitiveDataFields) {
            this.sensitiveDataFields = sensitiveDataFields;
            return (B) this;
        }

        public B frameLengthFieldLength(int frameLengthFieldLength) {
            this.frameLengthFieldLength = frameLengthFieldLength;
            return (B) this;
        }

        public B frameLengthFieldOffset(final int frameLengthFieldOffset) {
            this.frameLengthFieldOffset = frameLengthFieldOffset;
            return (B) this;
        }

        public B frameLengthFieldAdjust(final int frameLengthFieldAdjust) {
            this.frameLengthFieldAdjust = frameLengthFieldAdjust;
            return (B) this;
        }

        @Deprecated
        public B withSensitiveDataFields(int... sensitiveDataFields) {
            return sensitiveDataFields(sensitiveDataFields);
        }

        public B workerThreadsCount(int numberOfThreads) {
            this.workerThreadsCount = numberOfThreads;
            return (B) this;
        }
    }

}
